#include "GLWidget.h"

#include <QtGui>
#include <math.h>
#include <iostream>
#include <limits>

using namespace std;

#include "Scene.h"
#include "Camera.h"
#include "Loader.h"


GLWidget::GLWidget(QWidget *parent)
    : QGLWidget(QGLFormat(QGL::DoubleBuffer | QGL::SampleBuffers), parent)
{
    setFocusPolicy(Qt::StrongFocus);

    m_scene = NULL; 
    m_spinning = false;
}

GLWidget::~GLWidget()
{
}

void GLWidget::setScene(Scene *scene)
{
    m_scene = scene;
}


void GLWidget::initializeGL()
{
    glClearColor(0,0,0,1);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);
    glEnable(GL_MULTISAMPLE);
    glEnable(GL_NORMALIZE);
    glShadeModel(GL_SMOOTH);
}


void GLWidget::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    if(m_scene)
        m_scene->draw();
}


void GLWidget::resizeGL(int width, int height)
{
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    if(m_scene)
        m_scene->getCamera()->applyProjection(width, height);
}

void GLWidget::keyPressEvent ( QKeyEvent * event )
{
    const float moveFact = 0.3;
    const float turnFact = 2.5;

    Camera* camera = m_scene->getCamera();
    switch(event->key())
    {
        case Qt::Key_Up :
            if(event->modifiers() == Qt::SHIFT)
                camera->turnUp(turnFact);
            else
                camera->goAhead(moveFact);
            break;
        case Qt::Key_Down :
            if(event->modifiers() == Qt::SHIFT)
                camera->turnDown(turnFact);
            else
                camera->goBack(moveFact);
            break;
        case Qt::Key_Right :
            if(event->modifiers() == Qt::SHIFT)
                camera->goRight(moveFact);
            else
                camera->turnRight(turnFact);
            break;
        case Qt::Key_Left :
            if(event->modifiers() == Qt::SHIFT)
                camera->goLeft(moveFact);
            else
                camera->turnLeft(turnFact);
            break;
    }

    updateGL();
}

void GLWidget::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
    {
        m_currentPos = event->pos();
        m_spinning = true;
    }
}

void GLWidget::mouseReleaseEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
    {
        m_spinning = false;
    }
}

void GLWidget::mouseMoveEvent(QMouseEvent *event)
{
    if(!m_scene)
        return;

    if(m_spinning)
    {
        QPoint d = event->pos() - m_currentPos;
        m_currentPos = event->pos();

        if(event->modifiers() & Qt::SHIFT)
        {
            m_scene->getCamera()->goLeft(d.x() * 0.01);
            m_scene->getCamera()->goUp(d.y() * 0.01);
        }
        else
        {
            m_scene->getCamera()->turnLeft(d.x() * 0.1);
            m_scene->getCamera()->turnUp(d.y() * 0.1);
        }

        updateGL();
    }
}

void GLWidget::wheelEvent(QWheelEvent *event)
{
    if(m_scene)
    {
        m_scene->getCamera()->goAhead(event->delta()*0.01);
        updateGL();
    }
}
